package cn.fengLone.pay.service.impl;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.fengLone.pay.dao.BillHisDao;
import cn.fengLone.pay.dao.PayInfoDao;
import cn.fengLone.pay.dao.UnionPayFullDao;
import cn.fengLone.pay.dao.WebSiteDao;
import cn.fengLone.pay.dao.WeiXinFullDao;
import cn.fengLone.pay.entity.AliPayFull;
import cn.fengLone.pay.entity.BillHisInfo;
import cn.fengLone.pay.entity.PayInfo;
import cn.fengLone.pay.entity.UnionPayFullInfo;
import cn.fengLone.pay.entity.WebSite;
import cn.fengLone.pay.entity.WeiXinFull;
import cn.fengLone.pay.exception.BaseException;
import cn.fengLone.pay.service.ReconciliationService;
import cn.fengLone.pay.util.SimpleUtil;
import cn.fengLone.pay.util.SpringUtil;
import cn.fengLone.pay.util.RSA.RSAUtil;
import cn.fengLone.pay.util.unionPay.UnionPayUtil;
import cn.fengLone.pay.util.wechat.WeiXinPayUtil;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 
 * 第三方系统对账Service实现类
 * 
 * @author Guo Pengfei
 * 
 * @compony 深圳风轮科技有限公司
 * 
 * @date 2017-08-22
 * 
 */
@Service("ReconciliationService")
@Transactional(rollbackFor=Exception.class)
public class ReconciliationServiceImpl implements ReconciliationService{
	private Logger logger = Logger.getLogger(ReconciliationService.class);

	@Resource
	private WebSiteDao webSiteDao;
	
	@Resource
	private PayInfoDao payInfoDao;
	
	@Resource
	private WeiXinFullDao weiXinFullDao;
	
	@Resource
	private BillHisDao billHisDao;
	
	@Resource
	private UnionPayFullDao unionPayFullDao;
	
	
	/**
	 * 第三方系统自主查询订单状态
	 * @param siteToken 站点口令
	 * @param signValue 签名值
	 * @return
	 */
	public Map<String, Object> reconPayResult(String siteToken, String sign_value) throws Exception {
		Map<String, Object> resultMap = new HashMap<String, Object>();

		WebSite webSite = webSiteDao.querySite(siteToken);
		//1、校验siteToken是否存在
		if (webSite == null) {
			resultMap.put("return_code", 0);
			resultMap.put("return_msg", SpringUtil.getI18nMsg("no_site"));
			return resultMap;
		}
		//1、审核状态
		if(webSite.getVerifyType() !='3'){
			//网站没审核没有通过
			resultMap.put("return_code", 0);
			resultMap.put("return_msg", SpringUtil.getI18nMsg("site_no_pass"));
			return resultMap;
		}
		
		//2、校验签名数据是否为空
		if (sign_value == null || sign_value.trim().equals("")) {
			resultMap.put("return_code", 0);
			resultMap.put("return_msg", SpringUtil.getI18nMsg("no_sign_val"));
			return resultMap;
		}
		String decodeData = null;
		String publicKey  =null;
		try {
			//获取接入站点的公钥
			publicKey = webSite.getPublicKey();
			//解密站点发送的订单
			decodeData = RSAUtil.decryptByPublicKey(sign_value,publicKey);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BaseException(e,false,SpringUtil.getI18nMsg("decode_val_error"));
		}
		JSONObject jsonObject = null;
		try {
			//将字符串转为Json
			jsonObject = JSONObject.parseObject(decodeData);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BaseException(e,false,SpringUtil.getI18nMsg("decode_val_error"));
		}
		JSONArray  orderIds  = null;
		try {
			 orderIds = jsonObject.getJSONArray("order_ids");
		} catch (Exception e) {
			logger.error("return_msg\t:"+SpringUtil.getI18nMsg("out_orderIds_error"));
			e.printStackTrace();
			throw new BaseException(e,false,SpringUtil.getI18nMsg("out_orderIds_error"));
		}
		
		List<String> list = new ArrayList<String>();
		for (int i = 0; i < orderIds.size(); i++) {
			list.add(orderIds.getString(i));
		}
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
        paraMap.put("ids", list);
        paraMap.put("siteToken", siteToken);
		
//        List<Map<String, String>> orderResult = new ArrayList<Map<String, String>>();  //支付失败订单
        JSONArray jsonArray = new JSONArray();
        
		List<PayInfo> payInfos = payInfoDao.queryPayInfoByMertradeNums(paraMap);
		JSONObject tempJsonObject = null;
		if(payInfos == null || payInfos.isEmpty()){
			for(String orderName : list){
				tempJsonObject = new JSONObject();
				tempJsonObject.put("order_num", orderName);
				tempJsonObject.put("result_code", 0+"");//错误
				tempJsonObject.put("result_msg", SpringUtil.getI18nMsg("no_order_error"));
				jsonArray.add(tempJsonObject);
			}
			resultMap.put("return_code", 1);//成功
			String sign_val = RSAUtil.encryptByPublicKey(jsonArray.toJSONString(), publicKey);
			resultMap.put("respContent", sign_val);
			return resultMap;
		}else{
			WeiXinFull weiXinFull = null;
			AliPayFull aliPayFull =null;
			//....银联
			UnionPayFullInfo unionPayFullInfo = null;
			
			List<String> tempList = new ArrayList<String>();
			
			for(PayInfo payInfo : payInfos){
				if(payInfo.getPayResult()== '2' || payInfo.getPayResult()== '3'){
					//本平台中此订单的支付状态已经改变了，不再查询微信支付
					tempJsonObject = new JSONObject();
//					tempMap = new HashMap<String, String>();
					tempJsonObject.put("order_num", payInfo.getMertradeNum());
					tempJsonObject.put("result_code", 1+"");//成功
					tempJsonObject.put("payResult", payInfo.getPayResult()+"");//成功
					jsonArray.add(tempJsonObject);
					continue;
				}
				tempList.add(payInfo.getMertradeNum());//将所有的第三方订单号码临时存储
				String payType = payInfo.getPayType();//支付方式
				if(payType.equals("APP") || payType.equals("NATIVE")){
					//微信APP支付或者微信扫码支付
					checkWechatPayType(jsonArray ,weiXinFull,payInfo);
				}else if(payType.equals("alipay")){
					/////支付宝支付处理
					checkAliPayType(jsonArray ,aliPayFull,payInfo);
				}else if(payType.equals("")){
					//银联支付
					checkUnionPayType(jsonArray ,unionPayFullInfo,payInfo);
				}
			}
			
			if(tempList.size()>0 && list.size() > tempList.size()){
				//第三方系统中查询的订单中存在本系统没保存的订单
				for(String mertradeNum : list){
					if(tempList.contains(mertradeNum))
						continue;
					//将没有查找到的订单保存起来，返回给第三方系统
					JSONObject tempJsonObject1 = new JSONObject();
					tempJsonObject1.put("order_num", mertradeNum);
					tempJsonObject1.put("result_code", 0+"");//失败
					tempJsonObject1.put("result_msg", SpringUtil.getI18nMsg("no_order_error"));//
					jsonArray.add(tempJsonObject1); 
				}
				
			}
		}
		
		resultMap.put("return_code", 1);//成功
		String sign_val = RSAUtil.encryptByPublicKey(jsonArray.toJSONString(), publicKey);
		resultMap.put("respContent", sign_val);
		
		return resultMap;
	}

	/**
	 * 查询微信支付订单支付状态
	 * @param jsonArray  所有查询后的订单数据集合
	 * @param aliPayFull  阿里支付配置
	 * @param payInfo   要查询的订单信息
	 * @throws Exception
	 */
	private void checkAliPayType(JSONArray jsonArray, AliPayFull aliPayFull,
			PayInfo payInfo) {
		System.out.println("阿里支付主动对账功能未开放");
	}

	/**
	 * 查询微信支付订单支付状态
	 * @param jsonArray  所有查询后的订单数据集合
	 * @param weiXinFull  微信配置
	 * @param payInfo   要查询的订单信息
	 * @throws Exception
	 */
	private void checkWechatPayType(JSONArray jsonArray,WeiXinFull weiXinFull, PayInfo payInfo)throws Exception{

		JSONObject tempJsonObject = null;
		//微信App支付或者微信扫码支付，需要查找该用户的微信配置
		weiXinFull = initWechat(weiXinFull,payInfo);
		Map<String, String> queryMap = WeiXinPayUtil.queryOrder(weiXinFull,payInfo.getTradeNum());
		String return_code = queryMap.get("recode_code");
		if(return_code.equals("FAIL")){
			//业务处理失败，返回错误订单
			tempJsonObject = new JSONObject();
			tempJsonObject.put("order_num", payInfo.getMertradeNum());
			tempJsonObject.put("result_code", 0+"");//失败
			tempJsonObject.put("result_msg", queryMap.get("return_msg"));//成功
			jsonArray.add(tempJsonObject);
		}else{
			String result_code = queryMap.get("result_code");
			if(result_code.equals("FAIL")){
				//业务处理失败，返回错误订单
				tempJsonObject = new JSONObject();
				tempJsonObject.put("order_num", payInfo.getMertradeNum());
				tempJsonObject.put("result_code", 0+"");//失败
				tempJsonObject.put("result_msg", queryMap.get("err_code")+"======="+queryMap.get("err_code_des"));//成功
				jsonArray.add(tempJsonObject);
			}else{
				//return_code 和 result_code 均为SUCCESS
				String trade_state = queryMap.get("trad_state");//交易状态
				//1 微支付  2 支付成功 
				//3 支付失败 4 已关闭  5 已撤销(刷卡支付) 
				//6 用户支付中  7 转入退款
				tempJsonObject = new JSONObject();
//				tempJsonObject = new HashMap<String, String>();
				tempJsonObject.put("order_num", payInfo.getMertradeNum());
				tempJsonObject.put("result_code", 1+"");//成功
				if(trade_state.equals("NOTPAY")){
					//未支付,本系统默认订单状态就是未支付，不用修改订单状态，仅仅返回给第三方系统即可
					tempJsonObject.put("payResult", 1+"");//未支付
					jsonArray.add(tempJsonObject);
				}else{
					String payResult = null;
					if(trade_state.equals("SUCCESS"))
						payResult = "2";
					else if (trade_state.equals("PAYERROR")) 
						payResult = "3";
					else if (trade_state.equals("CLOSED")) 
						payResult = "4";
					else if (trade_state.equals("REVOKED")) 
						payResult = "5";
					else if (trade_state.equals("USERPAYING")) 
						payResult = "6";
					else if (trade_state.equals("REFUND")) 
						payResult = "7";
					
					tempJsonObject.put("payResult", payResult);
					
					jsonArray.add(tempJsonObject);
					payInfo.setPayResult(payResult.charAt(0));
					payInfoDao.updatePayResult(payInfo);
					// 保存对账信息
					BillHisInfo billHisInfo = billHisDao
							.queryBillByTradeNum(payInfo.getTradeId());
					if (billHisInfo == null)
						// 没有保存这个对账信息，新增对账信息
						saveBillHis(payInfo,'2');
				}
			}
		}
	}

	/**
	 * 初始化订单查询时的微信配置
	 * @param weiXinFull  微信配置信息 
	 * @param payInfo  订单信息
	 * @return
	 * @throws Exception
	 */
	private WeiXinFull initWechat(WeiXinFull weiXinFull, PayInfo payInfo) throws Exception{
		if(weiXinFull ==null){
			//第一次加载微信配置
			weiXinFull = weiXinFullDao.queryWeiXinFullBySiteId(payInfo.getWebSite().getId(),payInfo.getPayType());
			if(weiXinFull == null){	
				String appID = SimpleUtil.wechatPayMap.get("appID");
				String mchID = SimpleUtil.wechatPayMap.get("mchID");
				String certPath = SimpleUtil.wechatPayMap.get("certPath");
				String mchKey = SimpleUtil.wechatPayMap.get("mchKey");
				weiXinFull = new WeiXinFull();
				weiXinFull.setAppID(appID);
				weiXinFull.setMchID(mchID);
				weiXinFull.setMchKey(mchKey);
				weiXinFull.setCertPath(certPath);
			}
		}
		return weiXinFull;
	}
	/**
	 * 检查银联支付支付结果
	 * @param jsonArray  支付结果集合
	 * @param unionPayFullInfo  银联支付配置信息
	 * @param payInfo  订单
	 * @throws Exception 异常
	 */
	private void checkUnionPayType(JSONArray jsonArray,
			UnionPayFullInfo unionPayFullInfo, PayInfo payInfo)
			throws Exception {

		JSONObject tempJsonObject = null;
		// 微信App支付或者微信扫码支付，需要查找该用户的微信配置
		unionPayFullInfo = initUnionPay(unionPayFullInfo, payInfo);

		Map<String, String> queryMap = UnionPayUtil.queryOrder(
				unionPayFullInfo, payInfo);
		String return_code = queryMap.get("recode_code");
		if (return_code.equals("FAIL")) {
			// 业务处理失败，返回错误订单
			tempJsonObject = new JSONObject();
			tempJsonObject.put("order_num", payInfo.getMertradeNum());
			tempJsonObject.put("result_code", 0 + "");// 失败
			tempJsonObject.put("result_msg", queryMap.get("return_msg"));// 成功
			jsonArray.add(tempJsonObject);
		} else {
			String result_code = queryMap.get("result_code");
			if (result_code.equals("FAIL")) {
				// 业务处理失败，返回错误订单
				tempJsonObject = new JSONObject();
				tempJsonObject.put("order_num", payInfo.getMertradeNum());
				tempJsonObject.put("result_code", 0 + "");// 失败
				tempJsonObject.put("result_msg", queryMap.get("respMsg"));// 成功
				jsonArray.add(tempJsonObject);
			} else {

				tempJsonObject = new JSONObject();
				// tempJsonObject = new HashMap<String, String>();
				tempJsonObject.put("order_num", payInfo.getMertradeNum());
				tempJsonObject.put("result_code", 1 + "");// 成功
				// 1 微支付 2 支付成功
				// 3 支付失败 4 已关闭 5 已撤销(刷卡支付)
				// 6 用户支付中 7 转入退款
				tempJsonObject.put("payResult", "2");

				jsonArray.add(tempJsonObject);
				payInfo.setPayResult('2');
				payInfoDao.updatePayResult(payInfo);
				// 保存对账信息
				BillHisInfo billHisInfo = billHisDao
						.queryBillByTradeNum(payInfo.getTradeId());
				if (billHisInfo == null)
					// 没有保存这个对账信息，新增对账信息
					saveBillHis(payInfo, '2');
			}
		}
	}

	/**
	 * 初始化银联支付配置
	 * @param unionPayFullInfo  银联支付配置
	 * @param payInfo   订单
	 * @return
	 * @throws Exception
	 */
	private UnionPayFullInfo initUnionPay(UnionPayFullInfo unionPayFullInfo, PayInfo payInfo) throws Exception{
		if(unionPayFullInfo ==null){
			//第一次加载微信配置
			unionPayFullInfo = unionPayFullDao.queryUnionPayFullBySiteId(payInfo.getWebSite().getId());
			if(unionPayFullInfo == null){	
				String mchID = SimpleUtil.b2CGateWayMap.get("mchID");
				String certPath = SimpleUtil.b2CGateWayMap.get("certPath");
				String mchKey = SimpleUtil.b2CGateWayMap.get("mchKey");
				unionPayFullInfo = new UnionPayFullInfo();
				unionPayFullInfo.setMchID(mchID);
				unionPayFullInfo.setMchKey(mchKey);
				unionPayFullInfo.setCertPath(certPath);
			}
		}
		return unionPayFullInfo;
	}
	
	/**
	 * 保存对账历史表
	 * @param payInfo  订单信息表
	 * @param billType  对账方式     2：主动查询
	 * @return
	 * @throws Exception
	 */
	private boolean saveBillHis(PayInfo payInfo,char billType) throws Exception{
		BillHisInfo billHisInfo = new BillHisInfo();
		
		billHisInfo.setPayId(payInfo.getId());
		billHisInfo.setPayType(payInfo.getPayType());
		billHisInfo.setSiteId(payInfo.getWebSite().getId());
		billHisInfo.setTradeNum(payInfo.getTradeNum());
		billHisInfo.setBillType(billType);// 
		billHisInfo.setBillResult(payInfo.getPayType().charAt(0));
		billHisInfo.setBillMsg(payInfo.getPaymsg());
		billHisInfo.setCreateTime(new Timestamp(new Date().getTime()));
		billHisInfo.setResultTime(payInfo.getResultTime());

		billHisDao.addBillHis(billHisInfo);
		
		return true;
	}

	
}
